﻿using System.Text;
using UnityEngine;
using System.Xml;

namespace DL.Net.Editor.ProtocolTool
{
    public class GenerateCSharp
    {
        public static void GenerateMessage(XmlNodeList nodeList)
        {
            string usingNameSpace = "using Message.Base;\r\n";
            //字段名
            foreach (XmlNode messageNode in nodeList)
            {
                //消息id
                string messageID = messageNode.Attributes["id"].Value;

                //是否是系统消息
                string systemMessage = messageNode.Attributes["systemMessage"].Value;

                //命名空间
                string namespaceStr = messageNode.Attributes["namespace"].Value;
                //类名字
                string classNameStr = messageNode.Attributes["name"].Value;
                //data类型
                string dataType = messageNode.Attributes["datatype"]?.Value;

                string ConstructionMethod = $"  public {classNameStr}(int messageId) : base(messageId)" +
                                            "{}\r\n";
                //WriteIn
                string WriteInMethod =
                    $"   public override void WriteIn(byte[] buffer, int beginIndex,int length)\r\n" +
                    "{\r\n" +
                    $"   Data = {dataType}.Parser.ParseFrom(buffer, beginIndex, length);" +
                    "\r\n}";
                //Reset
                string ResetMethod = "  public override void Reset() {}\r\n";

                string messageStr;

                if (systemMessage != null && systemMessage == "1")
                {
                    //所有数据
                    messageStr = $"namespace {namespaceStr}" +
                                 "{\r\n" +
                                 $"public class {classNameStr} : BaseSystemMessage" +
                                 "{\r\n" +
                                 $"{ConstructionMethod}" +
                                 $"{ResetMethod}" +
                                 "\r\n}" +
                                 "\r\n}";
                }
                else
                {
                    //所有数据
                    messageStr = $"namespace {namespaceStr}" +
                                 "{\r\n" +
                                 $"public class {classNameStr} : BaseMessage<{dataType}>" +
                                 "{\r\n" +
                                 $"{ConstructionMethod}\n" +
                                 $"{WriteInMethod}\n" +
                                 $"{ResetMethod}\r\n" +
                                 "\r\n}" +
                                 "\r\n}";
                }


                GenerateFileTool.Generate($"{Application.dataPath}/Protocal/{namespaceStr}/Message/",
                    $"{classNameStr}.cs", usingNameSpace + messageStr);
            }
        }

        public static void GenerateMessagePool(XmlNodeList nodeList)
        {
            string usingnameSpace = "using System;\r\n" +
                                    "using System.Collections.Generic;\r\n" +
                                    "using DL.Tools;\r\n" +
                                    "using Message.Base;\r\n";

            string messageIDs = "   static List<int> messageIDs = new List<int> {";

            // string MessageTypeMap =
            //     "   private static readonly Dictionary<int, Func<BaseMessage>> MessageTypeMap = new Dictionary<int, Func<BaseMessage>>\r\n        {\r\n";

            string GetMessage = "   public static BaseMessage GetMessage(int id) " +
                                "{ " +
                                "   switch(id)" +
                                "   {\r\n" +
                                "   default: return null;\n";

            string GetmsgCaseFormat = "case {0}_ID: return Get{0}();\r\n";
            string msgCase = "";


            string ReturnMessage = "   public static void ReturnMessage(BaseMessage msg) " +
                                   "{ " +
                                   "   var id = msg.MessageID;" +
                                   "   switch(id)" +
                                   "   {\r\n";

            string ReturnmsgCaseFormat = "case {1}_ID: Return{1}(({0})msg);break;\r\n";
            string ReturnmsgCase = "";

            string GetMessageFormat = " public static {0} Get{1}() => {1}_pools.Get();\r\n";
            string ReturnMessageFormat = "  public static void Return{1}({0} msg) => {1}_pools.Return(msg);\r\n";
            var GetReturnStr = "";

            string PoolsFormat =
                "   private static ObjectPool<{0}> {1}_pools = new(()=> new({2}),null,(msg)=>msg.Reset(),null, true, 10, 25);\r\n";
            string PoolsStr = "";

            string messageLinkID = string.Empty;

            //开始构造
            StringBuilder sb = new();
            sb.Append(usingnameSpace);
            sb.Append("namespace Logic.Protocal.MessagePool\r\n" +
                 "{\r\n" +
                 "public static class MessagePool\r\n" +
                 "{\r\n");

            for (int i = 0; i < nodeList.Count; i++)
            {
                var xmlAttributeCollection = nodeList[i].Attributes;
                if (xmlAttributeCollection != null)
                {
                    string classNameStr = xmlAttributeCollection["name"].Value;
                    string messageID = xmlAttributeCollection["id"].Value;
                    string tempnamespace = xmlAttributeCollection["namespace"].Value;

                    //messageIDs
                    if (i == nodeList.Count - 1)
                    {
                        messageIDs += messageID;
                        // MessageTypeMap += $"{{{messageID},() => new {tempnamespace}.{classNameStr}({messageID})}}\r\n";
                    }
                    else
                    {
                        messageIDs += messageID + ",";
                        // MessageTypeMap += $"{{{messageID},() => new {tempnamespace}.{classNameStr}({messageID})}},\r\n";
                    }

                    PoolsStr += string.Format(PoolsFormat, $"{tempnamespace}.{classNameStr}", classNameStr,
                        $"{classNameStr}_ID");

                    GetReturnStr += string.Format(GetMessageFormat, $"{tempnamespace}.{classNameStr}", classNameStr);
                    GetReturnStr += string.Format(ReturnMessageFormat, $"{tempnamespace}.{classNameStr}", classNameStr);
                    msgCase += string.Format(GetmsgCaseFormat, classNameStr);
                    ReturnmsgCase += string.Format(ReturnmsgCaseFormat, $"{tempnamespace}.{classNameStr}",
                        classNameStr);
                    //GetMessage

                    //messageLinkID
                    messageLinkID += $"public const int {classNameStr}_ID = {messageID};\r\n";
                }
            }

            messageIDs += "};\r\n" + "public static List<int> MessageIDs => messageIDs;\r\n";

            // MessageTypeMap += "};\r\n";

            sb.Append(PoolsStr);

            // str += messageLinkID + messageIDs + MessageTypeMap + GetMessage + "}\r\n}\r\n";
            sb.Append(messageLinkID + messageIDs + GetReturnStr + GetMessage + msgCase + "}\r\n" + "}\r\n" +
                         ReturnMessage + ReturnmsgCase + "}\r\n}\r\n" + "}\r\n}\r\n");

            string dirPath = $"{Application.dataPath}/Protocal/MessagePool/";
            string fileName = $"MessagePool.cs";

            GenerateFileTool.Generate(dirPath, fileName, sb.ToString());
        }
    }
}